package bsf.baseservice.distributedcache.storage.redis;


import bsf.base.CallBack;
import bsf.baseservice.distributedcache.storage.BaseCache;
import bsf.baseservice.distributedcache.systemruntime.DistributedCacheConnectException;
import bsf.baseservice.distributedcache.systemruntime.DistributedCacheSerializationException;
import bsf.base.TimeSpan;
import bsf.redis.RedisDb;
import bsf.redis.RedisManager;
import bsf.serialization.json.JsonProvider;
import bsf.util.StringUtil;
import com.google.gson.JsonParseException;
import redis.clients.jedis.exceptions.JedisException;

//
//     * Redis存储
//     *序列化方面未来需要重写，并适应不同的存储方式；并提高序列化性能
//
public class RedisCache extends BaseCache
{
	private RedisDb redisdb = null;

	@Override
	public <T> T getValue(final Class<T> cls)
	{
		return (T)tryCatch(new CallBack.Func0() {
			@Override
			public Object invoke() {
				if (cls == String.class)
				{
					String stringValue = redisdb.getClient().get(cacheKey);
					return (stringValue instanceof String) ? (T)stringValue : null;
				}
				String bs = redisdb.getClient().get(cacheKey);
				if (bs == null)
				{
					return null;
				}
				if (bs.equals(""))
				{
					return null;
				}
				try
				{
					return new JsonProvider().deserialize(bs,cls);
				}
				catch (Exception exp)
				{
					throw new DistributedCacheSerializationException(StringUtil.nullToEmpty(bs) , exp);
				}
			}
		});
	}

	@Override
	public <T> boolean setValue(final T value, final TimeSpan expiretime)
	{
		return (boolean)tryCatch(new CallBack.Func0() {
			@Override
			public Object invoke(){
				if (value.getClass() == String.class)
				{
					String stringValue = (String)((value instanceof String) ? value : null);

					redisdb.getClient().set(cacheKey, stringValue);
					redisdb.getClient().expire(cacheKey,(int)expiretime.getSeconds());
				}
				String s = null;
				try
				{
					s = (value == null ? "" : new JsonProvider().serialize(value));
				}
				catch (Exception exp)
				{
					throw new DistributedCacheSerializationException(value.getClass(), exp);
				}
				redisdb.getClient().set(cacheKey, s);
				redisdb.getClient().expire(cacheKey,(int)expiretime.getSeconds());
				return true;
			}
		});
	}

	@Override
	public void delete()
	{
		tryCatch(new CallBack.Func0() {
			@Override
			public Object invoke()  {
				redisdb.getClient().del(cacheKey);
				return null;
			}
		});
	}

	@Override
	public void openConn(final String key)
	{
		tryCatch(new CallBack.Func0() {
			@Override
			public Object invoke()  {
				cacheKey = key;
				RedisCacheConfig serverconfig = (RedisCacheConfig)Config;
				RedisManager manager = new RedisManager();
				redisdb = manager.getPoolClient(StringUtil.nullToEmpty(serverconfig.Host), serverconfig.Port, serverconfig.Password,serverconfig.MaxPool,serverconfig.MinPool);
				return null;
			}
		});
	}


	private Object tryCatch(CallBack.Func0 action)
	{
		try
		{
			return action.invoke();
		}
		catch (JedisException e)
		{
			throw new DistributedCacheConnectException(e.getMessage(), e);
		}
		catch (JsonParseException e2)
		{
			throw new DistributedCacheSerializationException(e2);
		}

	}

	@Override
	public void close()
	{
		if (redisdb != null)
		{
			redisdb.dispose();
			redisdb = null;
		}
	}
}